# 序列化与反序列化

  • 序列化(Serialization):将内存里的对象转化为便于存储或传输的形式(比如,二进制数据流)
  • 反序列化(Deserialization):序列化的逆向操作

Java 原生序列化:只有实现了 java.io.Serializable 接口的类,才可以序列化

序列化版本号(serialVersionUID)

  • 进行反序列化时,JVM 会把传来的字节流中的 serialVersionUID 与本地实体类中的 serialVersionUID 进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常
  • 如果不显式指定 serialVersionUID,系统会在编译生成 class 文件时,自动生成一个 serialVersionUID,这种情况下,只有同一次编译生成的 class 才会拥有相同的 serialVersionUID
点击查看 Serializable 接口
// since JDK 1.1 
// 没有方法,只是一个标记接口
public interface Serializable

private static final long serialVersionUID = -5809782578272943999L;
1
2
3
4
5

# 序列流

java.io 提供了两个序列流,ObjectOutputStream 和 ObjectInputStream,这两个本质上也属于处理流,但是继承结构与其他处理流不同

# 1. ObjectOutputStream

// 定义 since JDK 1.1
public class ObjectOutputStream
extends OutputStream
implements ObjectOutput, ObjectStreamConstants

public ObjectOutputStream(OutputStream out) throws IOException

// 序列化方法
public final void writeObject​(Object obj) throws IOException
1
2
3
4
5
6
7
8
9

# 2. ObjectInputStream

// 定义 since JDK 1.1
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants

public ObjectInputStream(InputStream in) throws IOException

// 反序列化方法
public final Object readObject() throws IOException, ClassNotFoundException
1
2
3
4
5
6
7
8
9

# 样例代码

关键字 transient

  • 序列化时,默认所有属性都会被序列化
  • 如果希望某个属性,如密码,不被序列化,可以使用 transient 关键字
class Student implements Serializable {
    String name;
    transient int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

public static void serialize() throws IOException {
    Student student = new Student("rchen102", 22);
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    oos.writeObject(student);
    oos.close();
}

public static void deserialize() throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
    Student student = (Student) ois.readObject();
    System.out.println(student);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 自定义序列化方式

如果一个类不仅实现了 Serializable 接口,并且定义了 readObject(ObjectInputStream in) 和 writeObject(ObjectOutputStream out) 方法,则 ObjectOutputStream 会调用这个类的 writeObject 方法进行序列化,ObjectInputStream 会调用相应的 readObject 方法进行反序列化

参考链接 | java ArrayList的序列化分析 (opens new window)

Last Updated: 7/11/2020, 2:23:53 AM